package com.gjy.disruptor.uuid.newd.dis;

import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.RandomBasedGenerator;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SleepingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;

import java.util.concurrent.Executors;

/**
 * Disruptor事件生产者。
 * 直接接收Netty请求并发布到RingBuffer。
 *
 * @author gjy
 * @version 1.0
 * @since 2025-10-11 10:21:15
 */
public class UuidEventProducer {

    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(UuidEventProducer.class);

    private final RingBuffer<UuidEvent> ringBuffer;
    private final RandomBasedGenerator uuidGenerator;
    private final Disruptor<UuidEvent> disruptor;

    public UuidEventProducer() {

        // 2. 创建事件工厂
        UuidEventFactory factory = new UuidEventFactory();

        // 3. 指定RingBuffer大小
        int bufferSize = 131072;

        // 4. 构造Disruptor
        this.disruptor = new Disruptor<>(
                factory,
                bufferSize,
                Executors.defaultThreadFactory(),
                ProducerType.MULTI,
                new SleepingWaitStrategy(1, 1000) // 优化等待策略参数
        );

        // 5. 连接消费者
        UuidEventHandler eventHandler = new UuidEventHandler();
        disruptor.handleEventsWith(eventHandler);

        // 6. 启动Disruptor
        this.ringBuffer = disruptor.start();

        // 7. 初始化UUID生成器
        this.uuidGenerator = Generators.randomBasedGenerator();

        logger.info("Disruptor started with buffer size: {}", bufferSize);
    }

    /**
     * 尝试发布UUID生成事件到RingBuffer（非阻塞）
     */
    public boolean tryProduce(ChannelHandlerContext ctx, long requestId) {
        Object[] args = {uuidGenerator, ctx, requestId};
        return ringBuffer.tryPublishEvent(UuidEventTranslator.INSTANCE, args);
    }

    /**
     * 阻塞发布UUID生成事件到RingBuffer
     */
    public void produce(ChannelHandlerContext ctx, long requestId) {
        Object[] args = {uuidGenerator, ctx, requestId};
        ringBuffer.publishEvent(UuidEventTranslator.INSTANCE, args);
    }

    public void shutdown() {
        disruptor.shutdown();
        logger.info("Disruptor and ExecutorService shut down.");
    }

}
